##xxxxxxxxxxxxxxxxxxxxxxxxx C++ CMake 跨平台通用设置, 需要放在 project(xxx) 调用后面

##xxxxxxxxxxxxxxxxxxx toolchain configs; IDE 设置
# 让 generator 生成 clangd 需要的 build/compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)

##xxxxxxxxxxxxxxxxxxx c++ 语言设置
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
set(CMAKE_CXX_STANDARD 17) # C++ 标准
set(CMAKE_CXX_STANDARD_REQUIRED ON)

##xxxxxxxxxxxxxxxxxxx linux 二进制 属性
# set(CMAKE_SKIP_RPATH TRUE) # 禁用自动RPATH
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH OFF)

##xxxxxxxxxxxxxxxxxxx CUDA 全局设置
# 设置 CUDA 运行时库为动态链接
set(CMAKE_CUDA_RUNTIME_LIBRARY Shared)

##xxxxxxxxxxxxxxxxxxx 第三方库设置
# fmt::fmt
# 设置FMT_UNICODE=0禁用Unicode支持，避免fmt库中的static_assert错误
# 或者设置为1并确保所有编译器都使用/utf-8选项
add_compile_definitions("FMT_UNICODE=0")

##xxxxxxxxxxxxxxxxxxx MSVC c++ 设置
set(MY_CXX_CMPILE_OPTIONS "")
set(MY_CUDA_CMPILE_OPTIONS "")
if(MSVC)
    message(STATUS ">>>[YMY] Setting MSVC cl, link")

    # 1. 强制所有 C/C++ 目标使用动态运行时
    # set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
    message(STATUS "[YMY] MSVC compiler: ${CMAKE_CXX_COMPILER}")

    set(MY_CXX_CMPL_OPTS_MSVC "/utf-8" "/EHsc" "/Zc:__cplusplus" "/permissive-")
    list(JOIN MY_CXX_CMPL_OPTS_MSVC " " MY_CXX_CMPILE_OPTIONS)
    # message(STATUS "[YMY] MY_CXX_CMPILE_OPTIONS =>  ${MY_CXX_CMPILE_OPTIONS}")

    list(JOIN MY_CXX_CMPL_OPTS_MSVC "," MY_CUDA_CMPILE_OPTIONS)
    set(MY_CUDA_CMPILE_OPTIONS -Xcompiler="${MY_CUDA_CMPILE_OPTIONS}")
    # message(STATUS "[YMY] MY_CUDA_CMPILE_OPTIONS => ${MY_CUDA_CMPILE_OPTIONS}")
endif()


# add_compile_options("$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<COMPILE_LANGUAGE:CXX>>:${MY_CXX_CMPILE_OPTIONS}>")
# 可选的：为C++代码禁用特定警告
# add_compile_options("$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<COMPILE_LANGUAGE:CXX>>:/wd4819>")

# get_property(MY_DBG_DIR_COMP_OPTS DIRECTORY ${MY_ROOT_DIR} PROPERTY COMPILE_OPTIONS)
# message(STATUS "[ymy] MY_DBG_DIR_COMP_OPTS => ${MY_DBG_DIR_COMP_OPTS}")

##xxxxxxxxxxxxxxxxxxx Linux GCC 编译选项
set(MY_COMPILER_ID "${CMAKE_CXX_COMPILER_ID}")
if(NOT CMAKE_CXX_COMPILER_ID)
    set(MY_COMPILER_ID "${CMAKE_C_COMPILER_ID}")
endif()

set(MY_CXX_CMPILE_OPTIONS "")
if(MY_COMPILER_ID STREQUAL "GNU")
    message(STATUS "[YMY] GNU compiler: ${CMAKE_CXX_COMPILER}")

    set(MY_CXX_CMPL_OPTS_GCC -finput-charset=utf-8 -fexec-charset=utf-8 -Wall -Wextra -Wpedantic)
    list(JOIN MY_CXX_CMPL_OPTS_GCC " " MY_CXX_CMPILE_OPTIONS)

    list(JOIN MY_CXX_CMPL_OPTS_GCC "," MY_CUDA_CMPILE_OPTIONS)
    set(MY_CUDA_CMPILE_OPTIONS "-Xcompiler=${MY_CUDA_CMPILE_OPTIONS}")
    # message(STATUS "[YMY] MY_CUDA_CMPILE_OPTIONS => ${MY_CUDA_CMPILE_OPTIONS}")
endif()

# 为GCC编译器且为C++代码设置编译选项
# add_compile_options("$<$<AND:$<CXX_COMPILER_ID:GNU>,$<COMPILE_LANGUAGE:CXX>>:${MY_CXX_CMPILE_OPTIONS}>")
#xxxxxxxxxxxxxxxxxxxxxxxxx GPU, nvcc 设置; blackwell
#--------------- nvcc 选项, sync with cl, 但是分隔用 `,` 通过-Xcompiler传递
#add_compile_options("$<$<AND:$<CXX_COMPILER_ID:NVIDIA>,$<COMPILE_LANGUAGE:CUDA>>:${MY_CUDA_CMPILE_OPTIONS}>")

##xxxxxxxxxxxxxxxxxxx 告诉 NVCC 不要狗叫
if(CMAKE_CUDA_COMPILER AND TRUE)    
    set(CUDA_WARNING_SUPPRESSIONS
        -diag-suppress=27   # 抑制fmt中的字符值超出范围警告
        -diag-suppress=128  # 抑制fmt中的"loop is not reachable"警告
        -diag-suppress=2417 # 抑制fmt中的constexpr构造函数警告        
        -diag-suppress=1388 # 抑制spdlog中的DLL接口规范不一致警告        
        -diag-suppress=1394 # 抑制spdlog中的DLL接口字段警告
    )
    list(JOIN CUDA_WARNING_SUPPRESSIONS " " CUDA_WARNING_SUPPRESSIONS)
    set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} ${CUDA_WARNING_SUPPRESSIONS}")
endif()

#================== apply flags
#---- https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_FLAGS.html
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MY_CXX_CMPILE_OPTIONS}")
message(STATUS ">>>[YMY] CMAKE_CXX_FLAGS => ${CMAKE_CXX_FLAGS}")
#----
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} ${MY_CUDA_CMPILE_OPTIONS}")
message(STATUS ">>>[YMY] CMAKE_CUDA_FLAGS => ${CMAKE_CUDA_FLAGS}")